package com.itmck.mq.confirm;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.UUID;

@Component
@Slf4j
public class SendConfirm implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;


    /**
     * 发送消息, 构建自定义对象消息
     */
    public void sendMessage(String exchange, String routKey, String message) {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);

        /**
         * 自定义对象，消息唯一ID，
         * 每个发送的消息都需要配备一个 CorrelationData 相关数据对象，
         * CorrelationData 对象内部只有一个 id 属性，用来表示当前消息唯一性。
         * 真实场景是需要做业务无关消息 ID 生成，同时要记录下这个 id 用来纠错和对账。
         */
        String ids = UUID.randomUUID().toString();
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        // 发送消息
        rabbitTemplate.convertAndSend(exchange, routKey, message, correlationData);
        log.info("消息已发送，messageId={}", ids);
    }

    /**
     * 成功接收后回调, 确认消息被rabbitmq成功接收
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String s) {
        String messageId = correlationData.getId();
        if (ack) {
            // 如果成功接收了，就修改消息记录表的状态为success。
            log.info("消息发送成功, messageId={}", messageId);
        } else {
            //失败则进行具体的后续操作:重试 或者补偿等手段
            log.error("消息发送失败, messageId={}", messageId);
        }
    }

    /**
     * 失败后回调
     */
    @Override
    public void returnedMessage(Message message, int i, String s, String s1, String s2) {
        byte[] body = message.getBody();
        MessageProperties messageProperties = message.getMessageProperties();
        String messageId = messageProperties.getMessageId();
        log.error("messageId:{},消息发送失败, body={}", messageId, new String(body));
    }
}